package nl.xs4all.dylanschell.deckprinter.parser;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import nl.xs4all.dylanschell.deckprinter.model.CardInDeck;
import nl.xs4all.dylanschell.deckprinter.model.DeckDescriptor;
import nl.xs4all.dylanschell.deckprinter.services.DeckParser;
import org.octgn.types.CTCard;
import org.octgn.types.CTDeck;
import org.octgn.types.CTSection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
import java.util.UUID;

@Singleton
public class OCTGNDeckParser implements DeckParser
{
    private Unmarshaller unmarshaller;
    private XMLInputFactory inputFactory;
    private static final Logger logger = LoggerFactory.getLogger(OCTGNDeckParser.class);

    @Inject
    public OCTGNDeckParser(JAXBContext ctx, XMLInputFactory inputFactory) throws JAXBException
    {
        unmarshaller = ctx.createUnmarshaller();
        this.inputFactory = inputFactory;
    }

    public DeckDescriptor parseDeck(URL url, String name)
    {
        try
        {
            return parseDeck(url.openStream(), name);
        } catch (IOException e)
        {
            e.printStackTrace();
        }
        return null;
    }

    public DeckDescriptor parseDeck(InputStream is, String name)
    {
        try
        {
            XMLStreamReader reader = inputFactory.createXMLStreamReader(is);
            CTDeck deck = unmarshaller.unmarshal(reader, CTDeck.class).getValue();
            DeckDescriptor descriptor = new DeckDescriptor(name);
            for (CTSection section : deck.getSection())
            {
                for (CTCard card : section.getCard())
                {
                    String cardId = card.getId();
                    CardInDeck cid = new CardInDeck(card.getValue(), card.getQty() == null ? 1 : card.getQty(),
                                                    cardId != null ? UUID.fromString(cardId) : null);
                    List<CardInDeck> cardsInSection = descriptor.getCardsInSection(section.getName());
                    cardsInSection.add(cid);
                }
            }
            return descriptor;
        } catch (JAXBException e)
        {
            logger.error("Unable to parse deck", e);
        } catch (XMLStreamException e)
        {
            logger.error("Unable to parse deck", e);
        } finally
        {
            try
            {
                is.close();
            } catch (IOException e)
            {
                logger.error("Unable to parse deck", e);
            }
        }
        return null;
    }
}
